package tool;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateFormatUtils;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.app.VelocityEngine;
import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.api.ProgressCallback;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.internal.DefaultShellCallback;
import org.mybatis.generator.internal.NullProgressCallback;

public class CodeGenerator {

	private static File classPath = new File(System.getProperty("user.dir")+File.separator+"target"+File.separator+"classes");
	
	private static File resultDirectory = new File(classPath.getPath()+File.separator+"result");
	
	private static File mybatisDirectory = new File(classPath.getPath()+File.separator+"mybatis");
	
	private static File dataDirectory = new File(classPath.getPath()+File.separator+"data");
	
	private static File vmDirectory = new File(classPath.getPath()+File.separator+"vm");
	
	public static void main(String[] args) throws Exception {
		System.out.println(System.getProperty("user.dir"));
		clear();
		
		// 生成Mybatis domain和mapping文件
		genDomainAndMapping(mybatisDirectory);

		// 生成DAO，manager
		//genDaoAndManager(resultDirectory.getPath(), dataDirectory);
		System.out.println("ALL Done....");
	}

	private static void clear() throws IOException {
		FileUtils.deleteDirectory(resultDirectory);
	}

	public static void genDaoAndManager(String rootPath, File dataDirectory) throws Exception {
		Properties prop = new Properties();
		//prop.setProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH, "/vm");
		prop.put("file.resource.loader.class",
				"org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
		prop.setProperty(Velocity.ENCODING_DEFAULT, "UTF-8");
		prop.setProperty(Velocity.INPUT_ENCODING, "UTF-8");
		prop.setProperty(Velocity.OUTPUT_ENCODING, "UTF-8");
		VelocityEngine ve = new VelocityEngine(prop);
		ve.init();
		
		Collection<File> dataFiles  = FileUtils.listFiles(dataDirectory, new String[]{"properties"}, true);
		if(dataFiles!=null && !dataFiles.isEmpty()){
			Iterator<File> it = dataFiles.iterator();
			while(it.hasNext()){
				File dataFile = it.next();
				Properties dataProp = new Properties();
				InputStream inputStream = new FileInputStream(dataFile);
				Reader reader = new InputStreamReader(inputStream, "UTF-8");
				dataProp.load(reader);
				VelocityContext ctx = new VelocityContext();
				for (Object key : dataProp.keySet()) {
					ctx.put((String) key, dataProp.getProperty((String) key));
				}
				ctx.put("createTime", DateFormatUtils.format(new Date(),
						"yyyy-MM-dd HH:mm:ss"));
				String domainNameStr = dataProp.getProperty("domainName");
				String[] domainNames = domainNameStr.split(",");
				for (String domainName : domainNames) {
					if (!StringUtils.isBlank(domainName)) {
						ctx.put("domainName", domainName);
						
						Collection<File> vmFiles = FileUtils.listFiles(vmDirectory, new String[]{"vm"}, true);
						if(vmFiles!=null && !vmFiles.isEmpty()){
							Iterator<File> vmfileit = vmFiles.iterator();
							while(vmfileit.hasNext()){
								File templateFile = vmfileit.next();
								Template template = ve.getTemplate(templateFile.getPath(), "UTF-8");
								merge(template, ctx,
										rootPath + dataProp.getProperty("result.dir")
												+ "/dao/impl/" + domainName
												+ templateFile.getName()+".java");
							}
						}

						System.out.println(domainName
								+ " DAO and SERVICE 生成完成！");
					}
				}
			}
		}
	}

	public static void genDomainAndMapping(File directory) throws Exception {
		Collection<File> mybatisFiles = FileUtils.listFiles(
				directory, new String[] { "xml" }, true);
		if (mybatisFiles != null && !mybatisFiles.isEmpty()) {
			Iterator<File> it = mybatisFiles.iterator();
			while (it.hasNext()) {
				genByMybatis(it.next());
			}
		}
	}

	private static void genByMybatis(File configurationFile) throws Exception {
		List<String> warnings = new ArrayList<String>();
		ConfigurationParser cp = new ConfigurationParser(warnings);
		Configuration config = cp.parseConfiguration(configurationFile);
		//config.addClasspathEntry("D:\\Program Files\\apache-maven-3.3.9\\repo\\mysql\\mysql-connector-java\\5.1.36\\mysql-connector-java-5.1.36.jar");
		//config.addContext(context);

		MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config,
				new DefaultShellCallback(true), warnings);

		ProgressCallback progressCallback = new NullProgressCallback();

		myBatisGenerator.generate(progressCallback, new HashSet<String>(),
				new HashSet<String>());

	}

	private static void merge(Template template, VelocityContext ctx,
			String path) {
		PrintWriter writer = null;
		try {
			File file = new File(path);
			if (!file.exists()) {
				File dir = new File(file.getParent());
				if (!dir.exists()) {
					dir.mkdirs();
				}
				file.createNewFile();
			}
			writer = new PrintWriter(file);
			template.merge(ctx, writer);
			writer.flush();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			writer.close();
		}
	}

}
